package org.xx.armory.spring5;

import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.xx.armory.spring5.mvc.WebMvcConfig;
import org.xx.armory.spring5.security.WebSecurityConfig;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.SessionTrackingMode;
import java.util.EnumSet;

/**
 * 提供了统一入口。应用程序的入口类应当继承此类型。
 */
public abstract class ArmoryWebApplication
        extends SpringBootServletInitializer {
    protected ArmoryWebApplication() {
    }

    /**
     * 初始化应用程序。
     * <p>设置应用程序的一些默认属性。</p>
     *
     * @param application
     *         待初始化的应用程序。
     * @return 已初始化的应用程序。
     */
    private static SpringApplication initializeApplication(
            SpringApplication application
    ) {
        // application.setAdditionalProfiles(ADDITIONAL_PROFILE);
        return application;
    }

    /**
     * 启动应用程序。
     *
     * <p>通过命令行方式启动时调用此方法。</p>
     *
     * @param clazz
     *         应用程序的入口类型。
     * @param args
     *         命令行参数。
     */
    protected static void run(
            Class<? extends ArmoryWebApplication> clazz,
            String[] args
    ) {
        final var logger = LoggerFactory.getLogger(ArmoryWebApplication.class);
        logger.trace("Initialize application, then start up with command line arguments");

        initializeApplication(new SpringApplication(clazz)).run(args);
    }

    @Override
    public void onStartup(
            ServletContext servletContext
    )
            throws ServletException {
        super.onStartup(servletContext);

        // 禁止在URL中添加session id。
        servletContext.setSessionTrackingModes(EnumSet.of(SessionTrackingMode.COOKIE));
    }

    /**
     * 启动应用程序。
     *
     * <p>通过war包部署启动时<strong>自动</strong>调用此方法。</p>
     *
     * @param application
     *         待启动的应用程序。
     * @return 已启动的应用程序的上下文。
     */
    @Override
    protected WebApplicationContext run(
            SpringApplication application
    ) {
        final var logger = LoggerFactory.getLogger(ArmoryWebApplication.class);
        logger.trace("Initialize application, then start up as servlet");

        return super.run(initializeApplication(application));
    }

    //===================================================
    // 此处声明的所有配置都一定会被加载。

    @EnableWebMvc
    public static class DefaultWebMvcConfig
            extends WebMvcConfig {
    }

    @EnableWebSecurity
    public static class DefaultWebSecurityConfig
            extends WebSecurityConfig {
    }
}
